#include<iostream>
#include<unistd.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<string>
#include <cstdlib>
#include<string.h>
#include<stdio.h>
using namespace std;

#define CHECK_RET(q) if((q) == false){return -1;}
#define MAX_LISTEN 5
class TcpSocket{
  private:
    int _sockfd;
  public: 
    TcpSocket():_sockfd(-1){}
    bool Socket()//创建套接字
    {//int socket(int domain, int type, int protocol)
      _sockfd =  socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
      if (_sockfd < 0)
      {
        perror("socket error ");
        return false;
      }

      return true;

    }
    bool Bind(const std::string &ip, int port)//绑定地址信息
    {

      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(port);
      addr.sin_addr.s_addr = inet_addr(ip.c_str());
      socklen_t len = sizeof(addr);
      if( bind(_sockfd,(struct sockaddr*)&addr,len ) < 0)
      {
         perror("bind error");
         return false;
      }
      return true;

    }
    bool Listen(int backlog = MAX_LISTEN)//服务端开始监听
    {//int listen(int sockfd, int backlog);
      if(listen(_sockfd,backlog) < 0)
      {
        perror("listen error");
        return false;
      }
          return true;
    }
    bool Connect(const std::string &srv_ip, int srv_port)//向服务端发起连接请求
    {//int connect(int sockfd, struct sockaddr *addr, socklen t len);
      struct sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_port = htons(srv_port);
      addr.sin_addr.s_addr = inet_addr(srv_ip.c_str()) ;
      socklen_t len =sizeof(addr);
       
      if(connect(_sockfd,(struct sockaddr*)&addr,len) < 0)
      {
        perror("connect error");
        return false;
      }
      return true;
    }
    bool Accept(TcpSocket *new_sock, std::string *cli_ip, int *cli_port)//获取新建连接
    {//int accept(int sockfd, struct sockaddr *addr，socklen_ t *len)
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    int new_fd = accept(_sockfd,(struct sockaddr *)&addr,&len);

    if(new_fd < 0)
    {
      perror("accept error");
      return false;
    }
     new_sock->_sockfd = new_fd; 
     if(cli_ip != NULL) *cli_ip = inet_ntoa(addr.sin_addr);
     if(cli_port != NULL) *cli_port = ntohs(addr.sin_port);
      return true ;
    }
    bool Send(const std::string &data)
    {//ssize_t send(int sockfd, void *data, int len，int flag)
      ssize_t ret = send(_sockfd,data.c_str(),data.size(),0);
      if(ret < 0)
      {
        perror ("send error");
        return false;
      }
      return true;
    }
    bool Recv(std::string *buf)
    {
      // ssize_ t recv(int sockfd, void *buf, int len, int flag)
      char tmp[4096] = {0};
      ssize_t ret = recv(_sockfd,tmp,4096,0);
      if(ret < 0)
      {
        perror("recv error");
       return false;
      }else if(ret  == 0)
      {
        cout << "connetc shutdown!\n";
        return false;
      }
      buf->assign(tmp,ret);
      return true;
    }
    bool Close()
    {
      if(_sockfd > 0)
      { 
        close(_sockfd);
        _sockfd = -1;
        return false;
      }
           return true;
    }
};
